﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;
using System.Windows;
using HtmlAgilityPack;
using NLog;
using SellAvi.Classes;
using SellAvi.Model;
using SellAvi.Views;

namespace SellAvi
{
    class Authenticator
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
        private readonly AvitoUser _user;
        private static readonly NameValueCollection _userCredentials = new NameValueCollection
        {
            {"login", ""},
            {"password", ""},
            {"next", "/profile"},
        };

        public WebClientEx Client { get; set; }

        public Authenticator(AvitoUser usr)
        {
            _user = usr;
            _userCredentials.Set("login", usr.UserName);
            _userCredentials.Set("password", usr.UserPassword);
        }

        public bool Authenticate()
        {

            try
            {
                //BrowserClientEx.DefaultHeaders[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
                //BrowserClientEx.DefaultHeaders[HttpRequestHeader.Referer] = "https://www.avito.ru/additem";
                //Client.ResponseUri = new Uri("https://www.avito.ru/additem");
                //Client.DefaultHeaders[HttpRequestHeader.Referer] = "https://www.avito.ru/additem";
                Client.DefaultHeaders[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
                //Client.Headers.Add("ContentType", "application/x-www-form-urlencoded");
                //Client.Headers.Add("Referer", "https://www.avito.ru/additem");
                var loginUrl = new Uri("https://m.avito.ru/profile/login");
                if (_user.UserCookie != null)
                {
                    Logger.Trace("Использование Cookie для входа");
                    Client.FillCookieContainer(_user.UserCookie, "https://www.avito.ru");
                    //OR
                    //Client.Headers[HttpRequestHeader.Cookie] = _user.UserCookie;
                }
                else
                {
                    Logger.Trace("Авторизация через POST запрос");
                    Client.UploadValues(loginUrl, _userCredentials);

                    //Если не произошел 302 редирект на страницу : /profile то: либо надо ввести каптчу, либо неверно введен пароль
                    if (Client.ResponseUri == loginUrl && (CaptchaImagePath = TryParseCaptchaFromHtml(Client.ResponseHtml)) != null)
                    {
                        CreateCaptchaConfirmationWindow();
                        if (ResolvedCaptchaText != null)
                        {
                            _userCredentials.Set("captcha", ResolvedCaptchaText);
                            ResolvedCaptchaText = null; //todo: необходимо промониторить поведение повторного ввода защитного кода
                            Authenticate();
                        }

                    }
                }
                return true;

            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message);
                MessageBox.Show(ex.Message);
                return false;
            }

        }

        public bool CheckAuthorization()
        {
            Logger.Trace("Проверка доступности профиля пользователя");
            Uri checkUrl = new Uri("https://www.avito.ru/profile");
            bool authorizationSucceed = false;
            try
            {
                Client.DownloadStringWithNotification(checkUrl);
                // BUG: Проблема дублирования Cookie в CookieContainer для Domain  "www.avito.ru" и ".avito.ru", по этому удаляем лишнее
                // Т.К. через 1 - 2 дня вознизают проблемы с рассылкой сообщений и постингом товаров
                // Решение: т.к. свежие куки, присланные сервером имеют другой домен ".avito.ru", а не "www.avito.ru"
                // то куки с доменом www.avito.ru имеют меньший приоритет
                // http://stackoverflow.com/questions/1047669/cookiecontainer-bug
                // проблема решена в методе Client.FillCookieContainer

                authorizationSucceed = (Client.ResponseUri == checkUrl);
                if (/*_user.UserCookie != null && */authorizationSucceed == false)
                {
                    Logger.Debug("При проверке авторизации произошел редирект на страницу {0}", Client.ResponseUri);
                }
                else
                {
                    //Соединение с сервером аналитики
                    if (Client.DownloadString(GetLicenseQuery(_user)) == "[ACCESS TERMINATED]")
                    {
                        authorizationSucceed = false;
                        throw new LicenceExpiredException(
                            "Пробный период закончился, продлите срок действия лицензии!");
                    }
                }
            }
            catch (LicenceExpiredException ex)
            {
                Logger.Error(ex);
                MessageBox.Show(ex.Message, "Необходимо продление лицензии", MessageBoxButton.OK, MessageBoxImage.Hand);
                IEHelpers.OpenWebBrowser("http://sellavi.pro/buy.html");
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
                MessageBox.Show(ex.Message);
            }

            return authorizationSucceed;

        }

        public string ResolvedCaptchaText { get; set; }
        public string CaptchaImagePath { get; set; }
        private void CreateCaptchaConfirmationWindow()
        {
            Window captchaWindow = new Window
            {
                DataContext = this,
                Width = 220,
                Height = 140,
                Title = "Окно ввода защитного кода",
                Content = new ControlCaptcha()
            };
            //captchaWindow.Show();
            captchaWindow.ShowDialog();

        }

        /// <summary>
        /// TODO: Аналогичный метод в TaskProductUploader
        /// </summary>
        /// <param name="htmlContent">Содержимое веб-страницы, предполагаемо содержащие каптчу</param>
        /// <param name="cip">Captcha Full Path (local)</param>
        /// <returns></returns>
        private string TryParseCaptchaFromHtml(string htmlContent)
        {
            Directory.CreateDirectory("captcha");
            var captchaRegex = new Regex(@"\/captcha\?\d+");
            var captchaUrl = captchaRegex.Match(htmlContent).Value;
            if (captchaUrl == String.Empty)
            {
                Logger.Warn("Невозможно получить ссылку на изображение защитного кода с предоставленной страницы");
                return null;
            }
            var captachaFileName = "captcha/" + Path.GetRandomFileName() + ".jpg";
            Client.DownloadFile("https://www.avito.ru" + captchaUrl, captachaFileName);
            return Path.GetFullPath(captachaFileName);
        }

        public static string GetLicenseQuery(AvitoUser usr, int action = 0)
        {
            _userCredentials.Set("login", usr.UserName);
            _userCredentials.Set("password", usr.UserPassword);
            return "http://ascii-art.su/sellavi/avito_analytics.php?action=" + action + "&user=" +
                   HttpUtility.UrlEncode(string.Join(",", _userCredentials.AllKeys.Select(key => _userCredentials[key])));
        }

        /// <summary>
        /// Заполнение информации о пользователе из настроек профиля avito
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public AvitoUser UpdateUserInformation(AvitoUser user)
        {
            Logger.Trace("Получение контактных данных пользователя");
            var htmlPage = new HtmlDocument();
            var phones = new List<string>();
            var profileHtml = Client.DownloadString("https://www.avito.ru/profile/settings");

            if (Client.ResponseUri == new Uri("https://www.avito.ru/profile/settings"))
            {
                try
                {
                    htmlPage.LoadHtml(profileHtml);
                    //HtmlAgilityPack.HtmlEntity.DeEntitize //System.Net.WebUtility.HtmlDecode
                    user.CompanyName = HtmlEntity.DeEntitize(htmlPage.GetElementbyId("fld_name").GetAttributeValue("value", ""));
                    var cm = htmlPage.GetElementbyId("fld_manager");
                    user.CompanyManager = (cm != null) ? HtmlEntity.DeEntitize(cm.GetAttributeValue("value", "")) : null;

                    //регион может отсутствовать в профиле
                    var regionCode =
                        htmlPage.DocumentNode.SelectSingleNode(
                            "//select[@name = 'locationId']/option[@selected='selected']").GetAttributeValue("value", null);
                    user.TRegion_Id = String.IsNullOrEmpty(regionCode) ? null : (int?)int.Parse(regionCode);

                    user.CompanyEmail =
                        htmlPage.DocumentNode.SelectSingleNode("//span[contains(@class, 'profile-settings-header__name')]")
                            .InnerText.Trim();
                    var phoneNodes = htmlPage.DocumentNode.SelectNodes("//tr[@class='settings-phones-item']/@data-phone");

                    foreach (HtmlNode link in phoneNodes)
                    {
                        phones.Add(link.GetAttributeValue("data-phone", ""));
                    }
                    user.CompanyPhones = String.Join(";", phones);
                    return user;
                }
                catch (Exception ex)
                {

                    Logger.Error("Ошибка получения данных о пользователе со страницы профиля: ", ex);
                    MessageBox.Show(
                        "При попытке получения контактной информации с сайта произошла ошибка, попробуйте обновить программу.",
                        "Ошибка чтения профиля", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            else
            {
                MessageBox.Show("Нельзя обновить информацию о пользователе, который не авторизирован в системе",
                    "Ошибка обновления", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            return null;

        }

        public void BrowserRequest(string url)
        {
            var htmlContent = "Отсутствует Html содержимое!";
            HttpWebRequest myRequest = (HttpWebRequest)HttpWebRequest.Create(url);

            CookieContainer _cookieContainer = new CookieContainer();

            myRequest.CookieContainer = _cookieContainer;

            using (HttpWebResponse webResponse = (HttpWebResponse)myRequest.GetResponse())
            {
                if (webResponse.StatusCode == HttpStatusCode.OK)
                {
                    using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
                    {
                        htmlContent = reader.ReadToEnd();
                    }
                }
            }

        }

    }

    [Serializable]
    public class LicenceExpiredException : Exception
    {
        public LicenceExpiredException()
        { }

        public LicenceExpiredException(string message)
            : base(message)
        { }

        public LicenceExpiredException(string message, Exception innerException)
            : base(message, innerException)
        { }
    }



}
